package com.example.fileupload.util;

import com.example.fileupload.dto.HealthCheckResult;
import com.example.fileupload.storage.StorageStrategy;
import com.example.fileupload.storage.StorageStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 存储健康检查工具类
 */
@Slf4j
@Component
public class StorageHealthChecker {

    @Autowired
    private StorageStrategyFactory storageStrategyFactory;

    // 健康检查结果缓存
    private final Map<String, HealthCheckResult> healthCache = new ConcurrentHashMap<>();

    /**
     * 检查指定存储策略的健康状态
     */
    public Optional<HealthCheckResult> checkStorageHealth(String storageType) {
        long startTime = System.currentTimeMillis();

        try {
            return storageStrategyFactory.executeWithStrategy(storageType, strategy -> {
                try {
                    boolean result = performHealthCheck(strategy, storageType);
                    long responseTime = System.currentTimeMillis() - startTime;
                    String message = result ? "存储策略连接正常" : "存储策略连接异常";
                    HealthCheckResult healthResult = new HealthCheckResult(result, message, responseTime);
                    healthCache.put(storageType, healthResult);
                    return healthResult;
                } catch (Exception e) {
                    long responseTime = System.currentTimeMillis() - startTime;
                    return new HealthCheckResult(false, "存储策略测试失败: " + e.getMessage(), responseTime);
                }
            });
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            HealthCheckResult errorResult = new HealthCheckResult(false, "存储策略不可用: " + storageType, responseTime);
            return Optional.of(errorResult);
        }
    }

    /**
     * 获取缓存的健康检查结果
     */
    public Optional<HealthCheckResult> getCachedHealth(String storageType, long maxCacheAgeMs) {
        try {
            HealthCheckResult cached = healthCache.get(storageType);

            if (cached != null && !cached.isExpired(maxCacheAgeMs)) {
                return Optional.of(cached);
            }

            // 缓存过期或不存在，执行新的检查
            return checkStorageHealth(storageType);
            
        } catch (Exception e) {
            log.error("获取缓存健康状态失败: {}", e.getMessage());
            return Optional.empty();
        }
    }

    /**
     * 异步检查所有可用存储策略的健康状态
     */
    public CompletableFuture<Map<String, HealthCheckResult>> checkAllStoragesAsync() {
        return CompletableFuture.supplyAsync(() -> {
            Map<String, HealthCheckResult> results = new ConcurrentHashMap<>();

            storageStrategyFactory.getAllStrategies()
                    .entrySet()
                    .parallelStream()
                    .forEach(entry -> {
                        String storageType = entry.getKey().getValue();

                        checkStorageHealth(storageType)
                                .ifPresentOrElse(
                                        result -> results.put(storageType, result),
                                        () -> {
                                            log.warn("检查存储策略 {} 失败", storageType);
                                            results.put(storageType, new HealthCheckResult(
                                                    false, 
                                                    "检查失败", 
                                                    0
                                            ));
                                        }
                                );
                    });

            return results;
        });
    }

    /**
     * 执行具体的健康检查操作
     */
    private boolean performHealthCheck(StorageStrategy strategy, String storageType) {
        try {
            String testPath = generateTestPath();
            byte[] testData = "health-check-data".getBytes();

            // 1. 测试存储
            StorageStrategy.StorageResult storeResult = strategy.storeChunk(
                    testPath, 
                    new ByteArrayInputStream(testData), 
                    testData.length
            );
            
            if (!storeResult.isSuccess()) {
                log.debug("存储策略 {} 存储测试失败", storageType);
                return false;
            }

            // 2. 测试存在性检查
            boolean exists = strategy.exists(testPath);
            if (!exists) {
                log.debug("存储策略 {} 存在性检查失败", storageType);
                return false;
            }

            // 3. 测试删除
            boolean deleted = strategy.deleteFile(testPath);
            
            if (deleted) {
                log.debug("存储策略 {} 健康检查通过", storageType);
            } else {
                log.warn("存储策略 {} 删除测试失败", storageType);
            }
            
            return deleted;
            
        } catch (Exception e) {
            log.error("存储策略 {} 健康检查异常: {}", storageType, e.getMessage());
            return false;
        }
    }

    /**
     * 生成测试文件路径
     */
    private String generateTestPath() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"));
        return String.format("health-check/test-%s-%d.tmp", timestamp, System.nanoTime());
    }

    /**
     * 清理过期的健康检查缓存
     */
    public void cleanupExpiredCache(long maxAgeMs) {
        healthCache.entrySet().removeIf(entry -> entry.getValue().isExpired(maxAgeMs));
    }

    /**
     * 获取所有缓存的健康状态
     */
    public Map<String, HealthCheckResult> getAllCachedHealth() {
        return Map.copyOf(healthCache);
    }
} 